from collections import deque
from game.pathing import PathManager
import random
from collections import OrderedDict
from game.object.object import Object

class CharAttribute:
    def __init__(self):
        self.tru = 0
        self.dmg = 0
        self.regen = 0

#a postfix of 'a' indicates absolute value
#a postfix of 'p' indicates percentage value
    def apply_dmg_a(self, val):
        self.dmg += val

    def apply_dmg_p(self, val):
        self.dmg += self.dmg * (val / 100)

    def inc_tru_a(self, val):
        self.tru += val;

    def inc_tru_p(self, val):
        self.tru += self.dmg * (val / 100)

    def use_val(self):
        return self.tru - self.dmg


class CharProficiency:
    def __init__(self):
        self.lvl = 0;
        self.exp = 0;


class Character(Object):
    def __init__(self, name, **args):
        Object.__init__(self, name, **args)

        self.lvl = 0
        self.exp = 0
        self.dead = 0

        self.attribute = OrderedDict()
        self.equipment = OrderedDict()
        self.inventory = OrderedDict()

        self.pather = PathManager(['path'], ['none'])
        self.target = None
        self.target_path = None

    def die(self):
        self.dead = 1

    def back(self):
        if self.orient == 'n':
            return [self.x, self.y-1]
        if self.orient == 'e':
            return [self.x-1, self.y]
        if self.orient == 's':
            return [self.x, self.y+1]
        if self.orient == 'w':
            return [self.x+1, self.y]
        if self.orient == 'ne':
            return [self.x-1, self.y-1]
        if self.orient == 'se':
            return [self.x-1, self.y+1]
        if self.orient == 'sw':
            return [self.x+1, self.y+1]
        if self.orient == 'nw':
            return [self.x+1, self.y-1]
        return [self.x, self.y-1]

    #Causes the given attr: st to take val amount of damage
    def damage_attr(self, st, val):
        self.attribute[st].apply_dmg_a(val)
        return self.attribute[st].use_val()

    #Calculates the base attack rating for this character
    def attack_rating(self):
        #first, the base attack rating of the weapon is added

        #the proficiency for that weapon type is added

        #add in the strength of the character
        final = random.randint(1, self.attribute["dex"].use_val())
        return final

    def base_damage(self):
        final = random.randint(1, self.attribute["str"].use_val())
        return final

    #Calculate physical damage mitigation
    def mitigate(self):
        final = random.randint(1, self.attribute["end"].use_val())
        return final

    #Calculate reflex saving roll. Also used to calculate base dodge
    def reflex(self):
        final = random.randint(1, self.attribute["spd"].use_val())
        return final

    #Calculate physical resist check
    def phys_resist(self):
        pass

    #Calculate mental resist check
    def ment_resist(self):
        pass

    def add_inventory(self, items):
        for item in items:
            self.inventory[item.group].append(item)

    def move_step(self, data):
        if self.target is None:
            return 1

        if self.target_path is None:
            self.pather.clear_cache()
            self.target_path = self.pather.find_path(data.level, self.pos(), self.target, bias=10, dpen=5, diag=1)
            if self.target_path is None:
                return 1
            self.target_path.pop()

        i, dst = self.target_path.pop()
        px, py = self.x, self.y
        rdst = [dst.x - px, dst.y - py]
        data.act_mgr.perform("move", data, self.pos(), [rdst])
        if len(self.target_path) == 0 or (px == self.x and py == self.y):
            self.target = None
            self.target_path = None
            return 1

        return 0

class NPCharacter(Character):
    def __init__(self, name):
        Character.__init__(self, name)


    def update_ai(self, gd):
        xm, ym = random.randint(-1, 1), random.randint(-1, 1)
        if not (xm == 0 and ym == 0):
            gd.act_mgr.perform("move", gd, [self.x, self.y], [[xm, ym]])
        